home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 8 / QRZ Ham Radio Callsign Database - Volume 8.iso / pc / files / t_sys5 / unixkit.tgz / unixkit.tar / unixkit / common / bsd_nit.c < prev    next >
C/C++ Source or Header  |  1991-11-20  |  9KB  |  322 lines

  1. /* This is a very early release of a NIT driver for 4.3 BSD systems.
  2.  * You need to run this program as root. Please think about security
  3.  * during shell escapes, ftp-sessions etc.
  4.  * Define PACKET in config.h to use this driver.
  5.  *
  6.  * SM0RGV
  7.  */
  8. #include <stdio.h>
  9. #include <sys/types.h>
  10. #include <sys/time.h>
  11. #include <sys/param.h>
  12. #include <sys/stropts.h>
  13. #include <sys/file.h>
  14. #include <sys/ioctl.h>
  15. #include <sys/socket.h>
  16. #include <net/if.h>
  17. #include <netinet/in.h>
  18. #include <netinet/if_ether.h>
  19. #include <net/nit.h>
  20. #include <net/nit_if.h>
  21. #include <net/nit_pf.h>
  22. #include <net/packetfilt.h>
  23. #include "global.h"
  24. #include "config.h"
  25. #include "enet.h"
  26. #include "mbuf.h"
  27. #include "iface.h"
  28. #include "arp.h"
  29. #include "netuser.h"
  30. #include "pktdrvr.h"
  31. #include "asy.h"
  32. struct nitdrvr Nitdrvr[NIT_MAX];
  33. int nit_raw(),nit_stop();
  34. void nit_input();
  35.  
  36. extern struct iface *Ifaces;
  37. extern struct mbuf *Hopper;
  38. extern char Nospace[];
  39. int Nnit;
  40.  
  41. /* Define some TUN stuff to keep the compiler happy */
  42. struct tundrvr Tundrvr[TUN_MAX];
  43. int Ntun;
  44.  
  45. /* Attach a packet driver to the system
  46.  * argv[0]: hardware type, must be "packet"
  47.  * argv[1]: optional ethernet address or 0 for automatic assignment
  48.  * argv[2]: interface label, same as real interface, e.g., "le0"
  49.  * argv[3]: unused
  50.  * argv[4]: maximum transmission unit, bytes, e.g., "8192"
  51.  * argv[5]: optional IP address
  52.  */
  53. pk_attach(argc,argv,p)
  54.     int argc;
  55.     char **argv;
  56.     void *p;
  57. {
  58.           struct strioctl     si;
  59.           struct ifreq   ifr;
  60.           struct timeval timeout;
  61.       struct iface *if_nit;
  62.       struct nitdrvr *pp;
  63.       struct packetfilt filt;
  64.       u_short *fwp;
  65.       int i,if_flags;
  66.       char addr[EADDR_LEN+1], hostn[MAXHOSTNAMELEN];
  67.       
  68.       if(Nnit >= NIT_MAX){
  69.           tprintf("Too many nit drivers\n");
  70.           return -1;
  71.       }
  72.     if(if_lookup(argv[2]) != NULLIF){
  73.         tprintf("Interface %s already exists\n",argv[2]);
  74.         return -1;
  75.         }
  76.           if((if_nit = (struct iface *)calloc(1,sizeof(struct iface))) == NULLIF
  77.      ||(if_nit->name = strdup(argv[2])) == NULLCHAR){
  78.         if(if_nit != NULLIF)
  79.             free((char *)if_nit);
  80.         tprintf(Nospace);
  81.         return -1;
  82.     }
  83.     if_nit->addr = Ip_addr;
  84.     if(argc > 5)
  85.         if_nit->addr = resolve(argv[5]);
  86.     if(if_nit->addr == 0){
  87.         tprintf(Noipaddr);
  88.         free((char *)if_nit);
  89.         return -1;
  90.     }
  91.     pp = &Nitdrvr[Nnit];
  92.     if_nit->mtu = atoi(argv[4]);
  93.     if_nit->dev = Nnit;
  94.     if_nit->raw = nit_raw;
  95.     if_nit->stop = nit_stop;
  96.     pp->iface = if_nit;
  97.     if_nit->send = enet_send;
  98.     if_nit->output = enet_output;
  99.     if_nit->type = CL_ETHERNET;
  100.  
  101.           if((pp->IOser = open("/dev/nit", O_RDWR)) == -1) {
  102.           tprintf("Can't open /dev/nit\n");
  103.           free((char *)if_nit);
  104.           return -1;
  105.       }
  106.  
  107.       /* Arrange to get discrete messages from the stream. */
  108.           ioctl(pp->IOser, I_SRDOPT, (char *)RMSGD);
  109.  
  110.       /* Push the packet filtering module. It will be configured later */
  111.       ioctl(pp->IOser, I_PUSH, "pf");
  112.   
  113.           /* Configure the nit device, binding it to the proper
  114.              underlying interface, and setting nit_if-level flags. */
  115.           strncpy(ifr.ifr_name, argv[2], sizeof ifr.ifr_name);
  116.           si.ic_timout = INFTIM;
  117.  
  118.           si.ic_cmd = NIOCBIND;
  119.           si.ic_len = sizeof ifr;
  120.           si.ic_dp = (char *)𝔦
  121.           i = ioctl(pp->IOser, I_STR, (char *)&si);
  122.       if (i == -1) {
  123.           perror("ioctl bind");
  124.           free((char *)if_nit);
  125.           close (pp->IOser);
  126.           return -1;
  127.       }
  128.       /* Set promiscious mode, ie receive everything */
  129.       if_flags = NI_PROMISC;
  130.       si.ic_cmd = NIOCSFLAGS;
  131.       si.ic_len = sizeof if_flags;
  132.       si.ic_dp = (char *)&if_flags;
  133.       if (ioctl(pp->IOser, I_STR, (char *)&si) == -1) {
  134.           perror("ioctl");
  135.           free((char *)if_nit);
  136.           close(pp->IOser);
  137.           return -1;
  138.       }
  139.  
  140.       /* Get hardware Ethernet address from driver */
  141.       ioctl(pp->IOser,SIOCGIFADDR,&ifr);
  142.  
  143.       if (strcmp(argv[1],"0") == 0) {
  144.           /* Create our own Ethernet address! */
  145.           ifr.ifr_addr.sa_data[0] <<= 1;
  146.  
  147.           /* Check if it is unique */
  148.           i = ether_ntohost(hostn,(struct ether_addr *)ifr.ifr_addr.sa_data);
  149.           if (i && hostn[0] != '\0' && strcmp(hostn,Hostname)){
  150.           tprintf("Bad luck, could not use my Ethernet address.\n");
  151.           free((char *)if_nit);
  152.           close(pp->IOser);
  153.           return -1;
  154.           }
  155.       }
  156.       /* Use the user supplied ethernet address */
  157.       else gether(ifr.ifr_addr.sa_data,argv[1]);
  158.       
  159.       if((if_nit->hwaddr = malloc(EADDR_LEN)) == NULLCHAR){
  160.           free(if_nit->name);
  161.           free((char *)if_nit);
  162.           close(pp->IOser);
  163.           tprintf(Nospace);
  164.           return -1;
  165.       }
  166.       memcpy(if_nit->hwaddr,ifr.ifr_addr.sa_data,EADDR_LEN);
  167.  
  168.       /* Now try to configure the packet filter.
  169.          The filter should eliminate all packets except broadcast
  170.          packets and those directed to us. This is not very easily
  171.          done however. The following will stop most unwanted packets,
  172.          but not all.
  173.       */
  174.       fwp = filt.Pf_Filter;
  175.       for (i=0; i<EADDR_LEN; i += 2) {     /* EADDR_LEN == 6 */
  176.           /* Check for own address */
  177.           *fwp++ = ENF_PUSHWORD + i/2;
  178.           *fwp++ = ENF_PUSHLIT | ENF_EQ;
  179.        /* *fwp++ = ENF_PUSHLIT | ENF_CAND;*/
  180.           *fwp++ = *((u_short *) &if_nit->hwaddr[i]);
  181.           /* Check for broadcast address */
  182.           *fwp++ = ENF_PUSHWORD + i/2;
  183.           *fwp++ = ENF_PUSHLIT | ENF_EQ;
  184.           *fwp++ = *((u_short *) &Ether_bdcst[i]);
  185.           *fwp++ = ENF_CNOR;
  186.       }
  187.       filt.Pf_FilterLen = fwp - &filt.Pf_Filter[0];
  188.       i = ioctl(pp->IOser,NIOCSETF,&filt);
  189.       if (i == -1){ perror("ioctl pf"); return -1;}
  190.       /* This didn't filter out all unwanted addresses however! */
  191.  
  192.           /* Flush the read queue, to get rid of anything that accumulated
  193.              before the device reached its final configuration. */
  194.           ioctl(pp->IOser, I_FLUSH, (char *)FLUSHR);
  195.  
  196.       if ((pp->buffer = malloc(pp->iface->mtu)) == NULLCHAR) {
  197.           tprintf("Can't allocate buffer\n");
  198.           free(if_nit->name);
  199.           free((char *)if_nit);
  200.           close(pp->IOser);
  201.           return -1;
  202.       }
  203.       /* Enable interrupt for input to an empty queue */
  204.       ioctl(pp->IOser,I_SETSIG,S_INPUT|S_HIPRI|S_MSG);
  205.       if_nit->next = Ifaces;
  206.       Ifaces = if_nit;
  207.       newproc("ether_rx",2048,nit_input,0,pp,NULL,0);
  208.       pether(addr,if_nit->hwaddr);
  209.       tprintf("Attached %s (%s)\n",ifr.ifr_name,addr);
  210.       ++Nnit;
  211.       return 0;
  212. }
  213. /* This is the task that takes care of incoming ethernet packets.
  214.    It would be better to do all this at interrupt level (ie from inpint)
  215.    but the program seems to crash if you do memory allocation operations
  216.    from interrupt level without using alloc.c
  217. */
  218. void nit_input(unused,pp,unused2)
  219.     struct nitdrvr *pp;
  220.     void *unused2;
  221. {
  222.     int res,flags;
  223.     char i_state;
  224.     struct strbuf data, proto;
  225.     struct mbuf *bp;
  226.     struct phdr *phdr;
  227.     fd_set readfds;
  228.     struct timeval timeout;
  229.  
  230.     FD_ZERO (&readfds);
  231.     timeout.tv_sec = 0;
  232.     timeout.tv_usec = 35;
  233.     proto.buf = malloc(ETHERLEN);
  234.     proto.maxlen = ETHERLEN;
  235.     proto.len = 0;
  236.     data.buf = pp->buffer;
  237.     data.maxlen = pp->iface->mtu;
  238.     data.len = 0;
  239.     for (;;) {
  240.         /* If there are no new messages to fetch from the NIT interface,
  241.          * then wait until inpint() gives you a signal.
  242.          */
  243.         i_state = dirps();
  244.         while (FD_SET(pp->IOser,&readfds), select(NOFILE,
  245.             &readfds,(fd_set *)0,(fd_set *)0,&timeout) <= 0)
  246.         pwait(pp);
  247.         restore(i_state);
  248.         flags = 0;
  249.         res = getmsg(pp->IOser,&proto,&data,&flags);
  250.         if (res == -1)
  251.         perror("getmsg");
  252.  
  253.         /* Process the packet.
  254.         /* Since I didn't manage to make the filter inhibit all unwanted
  255.            packets we must check the destination address one more time */
  256.         if (memcmp(pp->iface->hwaddr,data.buf,EADDR_LEN)
  257.         && memcmp(Ether_bdcst,data.buf,EADDR_LEN))
  258.         continue;
  259.  
  260.         if((bp = alloc_mbuf(data.len+sizeof(struct phdr))) == NULLBUF){
  261.         tprintf(Nospace);
  262.         continue;
  263.         }
  264.         memcpy(bp->data+sizeof(struct phdr),data.buf,data.len);
  265.         /* Generate descriptor header */
  266.         phdr = (struct phdr *)bp->data;
  267.         phdr->iface = pp->iface;
  268.         phdr->type = CL_ETHERNET;
  269.         bp->cnt = data.len + sizeof(struct phdr);
  270.         if (res & MOREDATA)
  271.         tprintf("Problems, packet truncated!\n");
  272.         enqueue(&Hopper,bp);
  273.     }
  274. }
  275. /* Send raw packet (caller provides header) */
  276. int
  277. nit_raw(iface,bp)
  278. struct iface *iface;    /* Pointer to interface control block */
  279. struct mbuf *bp;        /* Data field */
  280. {
  281.     register struct nitdrvr *pp;
  282.     struct mbuf *bp1;
  283.     struct strbuf proto,data;
  284.     struct sockaddr sock;
  285.     short size;
  286.  
  287.     pp = &Nitdrvr[iface->dev];
  288.  
  289. /*    pp->stats.xmit++;*/
  290.  
  291.     size = len_p(bp);
  292.  
  293.     if(size < RUNT)
  294.         size = RUNT;
  295.     if(bp->next != NULLBUF){
  296.     /* Copy to contiguous buffer, since driver can't handle mbufs */
  297.         bp1 = copy_p(bp,size);
  298.         free_p(bp);
  299.         bp = bp1;
  300.         if(bp == NULLBUF)
  301.             return -1;
  302.     } else
  303.         bp->cnt = size;    /* Make sure packet size is big enough */
  304.  
  305.     dump(iface,IF_TRACE_OUT,CL_ETHERNET,bp);
  306.  
  307.     /* Now send the packet to the NIT interface */
  308.     sock.sa_family = AF_UNSPEC;
  309.     memcpy(sock.sa_data,bp->data,ETHERLEN);
  310.     proto.buf = (char *) &sock;
  311.     proto.len = sizeof (struct sockaddr);
  312.     data.buf = bp->data+ETHERLEN;
  313.     data.len = bp->cnt-ETHERLEN;
  314.     if (putmsg(pp->IOser,&proto,&data,0) == -1)
  315.         perror("putmsg");
  316.     free_p(bp);
  317.     return 0;
  318.     }
  319.  
  320. int nit_stop()
  321. {}
  322.